﻿#include"snake.h"

void PanelDevise(void)
{
	system("mode con cols=170 lines=45");
	system("title  原神 ");
}

void HideCursor()
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO curinfo;
	GetConsoleCursorInfo(handle, &curinfo);
	curinfo.bVisible = false;
	SetConsoleCursorInfo(handle, &curinfo);
}

void Setpos(int x, int y)
{
	COORD pos = { x,y };
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(handle, pos);
}

void menu_1()
{
	Setpos(85, 25);
	printf("欢迎到来贪吃蛇小游戏");
	Setpos(85, 42);
	printf("按任意键继续. . . ");
	getch();

}

void menu_2()
{
	Setpos(70, 24);
	printf("用 ↑ . ↓ . ← . → 分别控制蛇的移动， F3为加速，F4为减速\n");
	Setpos(70, 25);
	printf("F1原子崩坏技能，F2为崩坏降临");
	Setpos(70, 26);
	printf("加速将能得到更⾼的分数。");
	Setpos(75, 42);
	printf("按任意键继续. . . ");
	getch();

}

void Game_menu()
{
	for (int i = 0; i <= PANEL_ROWS; i++)
	{
		Setpos(0, i);
		printf("□");
		Setpos(PANEL_COLS - 1, i);
		printf("□");
		//printf("%d", i);
	}
	for (int i = 0; i < PANEL_COLS; i += 2)
	{
		Setpos(i, 0);
		printf("□");
		Setpos(i, PANEL_ROWS);
		printf("□");
		//Setpos(i, PANEL_ROWS+1);
		//printf("%d", i);
	}

	int x = PANEL_COLS+10, y = PANEL_ROWS / 3;
	Setpos(x, ++y);
	printf("不能穿墙，不能咬到自己.");
	Setpos(x, ++y);
	printf("用 ↑ . ↓ . ← . → 分别控制原批的移动.");
	Setpos(x, ++y);
	printf("每咬到或抽中一个神，将会获得相应分数并增加一个原节点");
	Setpos(x, y+=2);
	printf("F3为加速，F4为减速");
	Setpos(x, ++y);
	printf("加速分更高，减速分数更低\n");
	Setpos(x, ++y);
	printf("PS：跑得快不一定赢，不跌跟斗才叫成功");
	Setpos(x, y+=2);
	printf("F1原子崩坏射线，F2为崩坏降临");
	Setpos(x, y+=2);
	printf("F1原子崩坏射线：向前发射原石激光，激光所到之处比抽中神");
	Setpos(x, y+=2);
	printf("F2  崩坏降临  ：释放体内躁动的崩坏能，掏出648将原石撒向全屏，这把比拿下");
	Setpos(x, ++y);
	printf("PS：崩坏降临过于强大，需要扣除3个原节点，小心别把自己玩死了");
	Setpos(x, y+=2);
	printf("ESC：退出游戏  space：暂停游戏 ");
}

void induct()
{
	menu_1();
	system("cls");
	menu_2();
	system("cls");
	Game_menu();

}

pSnake SnakeMakeNode(int x, int y)
{
	pSnakeNode node = (pSnakeNode)malloc(sizeof(SnakeNode));
	assert(node);
	node->x = x;
	node->y = y;
	node->next = NULL;
	return node;
}

void InitSnake(pSnake ps) 
{
	SnakeNode* cur = NULL;
	for (int i = 0; i < SNAKELONG; i++)
	{
		cur = (pSnakeNode)malloc(sizeof(SnakeNode));
		if (cur == NULL)
		{
			perror("InitSnake()::malloc");
			return;
		}
		cur->x = POS_X + i * 2;
		cur->y = POS_Y ;
		cur->next = NULL;

		if (ps->_pSnake == NULL)
		{
			ps->_pSnake = cur;
		}
		else
		{
			cur->next = ps->_pSnake;
			ps->_pSnake = cur;
		}
	}

	cur = ps->_pSnake;
	while (cur)
	{
		Setpos(cur->x, cur->y);
		printf(BOOY);
		cur = cur->next;
	}
	ps->SleepTime = SLEEPTIME;
	ps->_Dir = RIGHT;
	ps->_FoodWeight = 10;
	ps->_score = 0;
	ps->_Status = OK;

}

void CreateFood(pSnake ps)
{
	int x = 0, y = 0;
	again:
	do
	{
		x = rand() % ((PANEL_COLS - 4) / 2) * 2;
		y = rand() % (PANEL_ROWS - 1) + 1;
	} while (x == 0);

	//do
	//{
	//	x = rand() % 53 + 2;
	//	y = rand() % 25 + 1;
	//} while (x % 2 != 0);

	pSnakeNode cur = ps->_pSnake;
	while (cur)
	{
		if (cur->x == x && cur->y == y)
		{
			goto again;
		}
		cur = cur->next;
	}
	pSnakeNode pfood = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (pfood == NULL)
	{
		perror("CreateFood()::malloc");
		return ;
	}
	pfood->x = x;
	pfood->y = y;
	pfood->next = NULL;
	Setpos(x, y);
	printf("神");
	ps->_pFood = pfood;
}

void pause()
{
	while (1)
	{
		Sleep(300);
		if (KEY_PRESS(VK_SPACE))
		{
			break;
		}
	}
	HideCursor();
}



int NextIsFood(pSnakeNode psn, pSnake ps)
{
	return (psn->x == ps->_pFood->x) && (psn->y == ps->_pFood->y);
}

void EatFood(pSnakeNode psn, pSnake ps)
{
	psn->next = ps->_pSnake;
	ps->_pSnake = psn;
	pSnakeNode cur = ps->_pSnake;
	while (cur)
	{
		Setpos(cur->x, cur->y);
		printf(BOOY);
		cur = cur->next;
	}
	ps->_score += ps->_FoodWeight;
	free(ps->_pFood);
	CreateFood(ps);
}

void NoFood(pSnakeNode psn, pSnake ps)
{
	psn->next = ps->_pSnake;
	ps->_pSnake = psn;
	pSnakeNode cur = ps->_pSnake;
	while (cur->next->next)
	{
		Setpos(cur->x, cur->y);
		printf(BOOY);
		cur = cur->next;
	}
	Setpos(cur->next->x, cur->next->y);
	printf("  ");
	free(cur->next);
	cur->next = NULL;
}

int KillByWall(pSnake ps)
{
	if (ps->_pSnake->x <= 0
		|| ps->_pSnake->y <= 0
		|| ps->_pSnake->x >= PANEL_COLS - 1
		|| ps->_pSnake->y >= PANEL_ROWS)
	{
		ps->_Status = KILL_BY_WALL;
		return 1;
	}
	return 0;
}

int KillBySelf(pSnake ps)
{
	pSnakeNode cur = ps->_pSnake->next;
	while (cur)
	{
		if ((ps->_pSnake->x == cur->x) && (ps->_pSnake->y == cur->y))
		{
			ps->_Status = KILL_BY_SELF;
			return 1;
		}
		cur = cur->next;
	}
	return 0;
}

void SnakeMove(pSnake ps)
{
	pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (pNextNode == NULL)
	{
		perror("SnakeMove()::malloc");
		return;
	}
	switch (ps->_Dir)
	{
		case UP:
		{
			pNextNode->x = ps->_pSnake->x;
			pNextNode->y = ps->_pSnake->y - 1;
		}break;
		case DOWN:
		{
			pNextNode->x = ps->_pSnake->x;
			pNextNode->y = ps->_pSnake->y + 1;
		}break;
		case LEFT:
		{
			pNextNode->x = ps->_pSnake->x - 2;
			pNextNode->y = ps->_pSnake->y;
		}break;
		case RIGHT:
		{
			pNextNode->x = ps->_pSnake->x + 2;
			pNextNode->y = ps->_pSnake->y;
		}break;
	}

	if (NextIsFood(pNextNode, ps))
	{
		EatFood(pNextNode, ps);
	}
	else
	{
		NoFood(pNextNode, ps);
	}

	KillByWall(ps);
	KillBySelf(ps);
}



void judSnake_i_j(pSnake ps,int* i,int* j)
{
	switch (ps->_Dir)
	{
	case UP:
		(*j)--;
		break;
	case DOWN:
		(*j)++;
		break;
	case LEFT:
		(*i) -= 2;
		break;
	case RIGHT:
		(*i) += 2;
		break;
	}

}

void SnakeEatBySkill(pSnake ps,int x,int y)
{
	if (x == ps->_pFood->x && y == ps->_pFood->y)
	{
		int i = ps->_pSnake->x,  j = ps->_pSnake->y;
		judSnake_i_j(ps, &i, &j);
		pSnakeNode node = SnakeMakeNode(i,j);
		node->next = ps->_pSnake;
		ps->_pSnake = node;

		pSnakeNode cur = ps->_pSnake;
		while (cur)
		{
			Setpos(cur->x, cur->y);
			printf(BOOY);
			cur = cur->next;
		}
		ps->_score += ps->_FoodWeight;
		free(ps->_pFood);
		CreateFood(ps);
	}
}

int KillBySkill(pSnake ps, int x, int y)
{
	pSnakeNode cur = ps->_pSnake;
	while (cur)
	{
		if (x == cur->x && y == cur->y)
		{
			ps->_Status = KILL_BY_SELF;
			return 1;
		}
		cur = cur->next;
	}
	return 0;
}

void SnakeSkill(pSnake ps)
{
	int i = ps->_pSnake->x, j = ps->_pSnake->y;
	int x = ps->_pSnake->x;
	int y = ps->_pSnake->y;
	int dir = ps->_Dir;
	int count = 0;
	switch (ps->_Dir)
	{
	case UP:
	{
		while (y > 1)
		{
			y--;
			if (count == 0)
				count = KillBySkill(ps, x, y);
			SnakeEatBySkill(ps, x, y);
			Setpos(x, y);
			printf(HONKAI_SKILL);
			Sleep(SKILLTIME);
		}
		j--;
		while (j >= 1 && count == 0)
		{
			
			Setpos(i, j);
			printf("  ");
			j--;
		}
	}break;
	case DOWN:
	{
		while (y < PANEL_ROWS-1)
		{
			y++;
			if (count == 0)
				count = KillBySkill(ps, x, y);
			SnakeEatBySkill(ps, x, y);
			Setpos(x, y);
			printf(HONKAI_SKILL);
			Sleep(SKILLTIME);
		}
		j++;
		while (j <= PANEL_ROWS-1 && count == 0)
		{
			
			Setpos(i, j);
			printf("  ");
			j++;
		}
	}break;
	case LEFT:
	{
		while (x > 2)
		{
			x -= 2;
			if (count == 0)
				count = KillBySkill(ps, x, y);
			SnakeEatBySkill(ps, x, y);
			Setpos(x, y);
			printf(HONKAI_SKILL);
			Sleep(SKILLTIME);
		}
		i-=2;
		while (i >= 2 && count == 0)
		{
			Setpos(i, j);
			printf("  ");
			i -= 2;
		}
	}break;
	case RIGHT:
		while (x < PANEL_COLS-3)
		{
			x += 2;
			if (count == 0)
				count = KillBySkill(ps, x, y);
			SnakeEatBySkill(ps, x, y);
			Setpos(x, y);
			printf(HONKAI_SKILL);
			Sleep(SKILLTIME);
		}
		i += 2;
		while (i <= PANEL_COLS-2 && count == 0)
		{
			
			Setpos(i, j);
			printf("  ");
			i += 2;
		}
	}
}
void PrintHonKaiSkill(char* s)
{
	char str[PANEL_COLS] = "\0";
	for (int i = 0; i < PANEL_COLS-3; i+=2)
	{
		strcat(str, s);
	}
	for (int j = 1; j < PANEL_ROWS; j++)
	{
		Setpos(2, j);
		printf("%s", str);
	}
}
void HonKaiBefall(pSnake ps)
{
	PrintHonKaiSkill(BEFALL_SKILL);
	Sleep(300);
	PrintHonKaiSkill("  ");
	int i = ps->_pSnake->x, j = ps->_pSnake->y;
	judSnake_i_j(ps, &i, &j);

	pSnakeNode node = SnakeMakeNode(i, j);
	node->next = ps->_pSnake;
	ps->_pSnake = node;

	pSnakeNode cur = ps->_pSnake;
	while (cur)
	{		
		if (cur != ps->_pSnake && cur->x == i && cur->y == j)
		{
			ps->_Status = KILL_BY_SELF;
		}
		Setpos(cur->x, cur->y);
		printf(BOOY);
		cur = cur->next;
	}
	ps->_score += ps->_FoodWeight;
	free(ps->_pFood);
	CreateFood(ps);
}

void JudLifeNode(pSnake ps)
{
	pSnakeNode cur = ps->_pSnake;
	
	int count = 0;
	pSnakeNode del = cur;
	if(cur && cur->next && cur->next->next&&cur->next->next&&
		cur->next->next->next && cur->next->next->next->next)
	{
		del = cur->next->next;
		ps->_pSnake = del->next;
		del->next = NULL;
		while (cur)
		{
			Setpos(cur->x, cur->y);
			printf("  ");

			del = cur;
			cur = cur->next;
			free(del);
			del = NULL;
		}
	}
	else
	{
		ps->_Status = KILL_BY_SELF;
	}

	while (cur)
	{
		Setpos(cur->x, cur->y);
		printf("  ");
		cur = cur->next;
	}
}


